package com.mycompany.inventory.viewmodel;

import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.Init;
import org.zkoss.image.AImage;
import org.zkoss.io.Files;
import org.zkoss.util.media.Media;
import org.zkoss.zhtml.Messagebox;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zul.Bandbox;
import org.zkoss.zul.Fileupload;
import org.zkoss.zul.Image;
import org.zkoss.zul.Window;
import org.zkoss.zul.Tab;

import com.mycompany.inventory.persistence.BillMaterialDAO;
import com.mycompany.inventory.persistence.CostingInfoDAO;
import com.mycompany.inventory.persistence.CustomFieldDAO;
import com.mycompany.inventory.persistence.InventoryDAO;
import com.mycompany.inventory.persistence.MediaDAO;
import com.mycompany.inventory.persistence.ProductCategoriesDAO;
import com.mycompany.inventory.persistence.ProductDAO;
import com.mycompany.inventory.persistence.ProductInventoryDAO;
import com.mycompany.inventory.persistence.SaleInfoDAO;
import com.mycompany.inventory.persistence.StorageInfoDAO;
import com.mycompany.inventory.persistence.TypeDAO;
import com.mycompany.inventory.persistence.UnitDAO;
import com.mycompany.inventory.persistence.VendorDAO;
import com.mycompany.inventory.persistence.VendorProductDAO;
import com.mycompany.inventory.pojo.BillMaterial;
import com.mycompany.inventory.pojo.CostingInfo;
import com.mycompany.inventory.pojo.CustomInfo;
import com.mycompany.inventory.pojo.Inventory;
import com.mycompany.inventory.pojo.MediaDTO;
import com.mycompany.inventory.pojo.Product;
import com.mycompany.inventory.pojo.ProductCategories;
import com.mycompany.inventory.pojo.ProductInventory;
import com.mycompany.inventory.pojo.SaleInfo;
import com.mycompany.inventory.pojo.StorageInfo;
import com.mycompany.inventory.pojo.Type;
import com.mycompany.inventory.pojo.Unit;
import com.mycompany.inventory.pojo.Vendor;
import com.mycompany.inventory.pojo.VendorProduct;
import com.mycompany.inventory.util.Constant;

public class ProductViewModel implements org.zkoss.zk.ui.event.EventListener{
	private String Id;
	private String name;
	private String description;
	private String remark;
	private String image;
	private String cost;
	private String storageInfoId;
	private boolean display;
	private BufferedImage bufferImg;
	Image pics;

	private Product selectedProduct;
	private List<Product> products = new ArrayList();
	ProductDAO productDAO = new ProductDAO();
	
	private Product selectedProductForMaterial;
	private List<Product> productForMaterial = new ArrayList();
	
	//product type
	private Type selectedType;
	private List<Type> type = new ArrayList<Type>();

	//product unit
	private Unit selectedUnit;
	private List<Unit> unit = new ArrayList<Unit>();	

	//product unit
	private Unit selectedSUnit;
	private List<Unit> sunit = new ArrayList<Unit>();
	
	//product unit
	private Unit selectedPUnit;
	private List<Unit> punit = new ArrayList<Unit>();	
	
	// Saleinfo
	private SaleInfo saleInfo;
	private List<SaleInfo> sale = new ArrayList<SaleInfo>();
	private SaleInfoDAO saleDAO = new SaleInfoDAO(); 
	// Inventory 
	private ProductInventory selectedInventory;
	private List<ProductInventory> productInvs = new ArrayList<ProductInventory>();
			
	// category
	private ProductCategories selectedCategory;
	private List<ProductCategories> categories = new ArrayList<ProductCategories>();
	
	//CostingInfo
	private CostingInfo selectedcostingInfo;
	private List<CostingInfo> costingInfos = new ArrayList<CostingInfo>();
	
	//Custom
	private CustomInfo custom;
	private List<CustomInfo> customs = new ArrayList<CustomInfo>();
	
	//StorageInfo
	StorageInfo storage = new StorageInfo();
	//Media
	MediaDTO media = new MediaDTO();
	
	//Location
	private Inventory selectedLocation;
	private List<Inventory> locations = new ArrayList<Inventory>();
	
	//Vendor
	private List<Vendor> lastVendor;
	private VendorDAO vDAO = new VendorDAO();
	private Vendor selectedVendor;
	private List<Vendor> vendors = new ArrayList<Vendor>();
	
	private Vendor selectedVendorForTab;
	private List<Vendor> vendorsForTab = new ArrayList();
	
	private Vendor selectedProductVendor;
	private List<Vendor> productVendors = new ArrayList();
	
	//Inv		
	private List<Inventory> inventories = new ArrayList<Inventory>();
	
	private Inventory selectedInvForTab;
	private List<Inventory> invsForTab = new ArrayList<Inventory>();
	
	private String quantityOnHand;
	//Material		
	private List<BillMaterial> materials = new ArrayList<BillMaterial>();
	private Product selectedMaterialProduct;
	private List<Product> materialProducts = new ArrayList();
	private Product selectedMaterialForTab;
	private List<BillMaterial> materialForTab = new ArrayList<BillMaterial>();
	private BillMaterial billMaterial = new BillMaterial();
	private int totalCost;	
	
	public void onEvent(Event evt) throws InterruptedException {
        if (evt.getName().equals("onOK")) {

        } else {	
        	return;
        }
    }

	/**
	 * @return the id
	 */
	public String getId() {
		return Id;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(String id) {
		Id = id;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the description
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * @param description the description to set
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * @return the remark
	 */
	public String getRemark() {
		return remark;
	}

	/**
	 * @param remark the remark to set
	 */
	public void setRemark(String remark) {
		this.remark = remark;
	}

	/**
	 * @return the image
	 */
	public String getImage() {
		return image;
	}

	/**
	 * @param image the image to set
	 */
	public void setImage(String image) {
		this.image = image;
	}
	
	public String getCost() {
		return cost;
	}

	public void setCost(String cost) {
		this.cost = cost;
	}
	
	public String getStorageInfoId() {
		return storageInfoId;
	}

	public void setStorageInfoId(String storageInfoId) {
		this.storageInfoId = storageInfoId;
	}

	/**
	 * @return the selectedProduct
	 */
	public Product getSelectedProduct() {
		return selectedProduct;
	}

	/**
	 * @param selectedProduct the selectedProduct to set
	 */
	public void setSelectedProduct(Product selectedProduct) {
		this.selectedProduct = selectedProduct;
	}

	/**
	 * @return the products
	 */
	public List<Product> getProductList() {
		return products;
	}

	/**
	 * @param products the products to set
	 */
	public void setProductList(List<Product> products) {
		this.products = products;
	}

	/**
	 * @return the selectedType
	 */
	public Type getSelectedType() {
		return selectedType;
	}

	/**
	 * @param selectedType the selectedType to set
	 */
	public void setSelectedType(Type selectedType) {
		this.selectedType = selectedType;
	}

	/**
	 * @return the type
	 */
	public List<Type> getType() {
		return type;
	}

	/**
	 * @param type the type to set
	 */
	public void setType(List<Type> type) {
		this.type = type;
	}
	
	/**
	 * @return the selectedUnit
	 */
	public Unit getSelectedUnit() {
		return selectedUnit;
	}

	/**
	 * @param selectedUnit the selectedUnit to set
	 */
	public void setSelectedUnit(Unit selectedUnit) {
		this.selectedUnit = selectedUnit;
	}

	/**
	 * @return the unit
	 */
	public List<Unit> getUnit() {
		return unit;
	}

	/**
	 * @param unit the unit to set
	 */
	public void setUnit(List<Unit> unit) {
		this.unit = unit;
	}
	
	/**
	 * @return the selectedSUnit
	 */
	public Unit getSelectedSUnit() {
		return selectedSUnit;
	}

	/**
	 * @param selectedSUnit the selectedSUnit to set
	 */
	public void setSelectedSUnit(Unit selectedSUnit) {
		this.selectedSUnit = selectedSUnit;
	}

	/**
	 * @return the sunit
	 */
	public List<Unit> getSunit() {
		return sunit;
	}

	/**
	 * @param sunit the sunit to set
	 */
	public void setSunit(List<Unit> sunit) {
		this.sunit = sunit;
	}

	/**
	 * @return the selectedPUnit
	 */
	public Unit getSelectedPUnit() {
		return selectedPUnit;
	}

	/**
	 * @param selectedPUnit the selectedPUnit to set
	 */
	public void setSelectedPUnit(Unit selectedPUnit) {
		this.selectedPUnit = selectedPUnit;
	}

	/**
	 * @return the punit
	 */
	public List<Unit> getPunit() {
		return punit;
	}

	/**
	 * @param punit the punit to set
	 */
	public void setPunit(List<Unit> punit) {
		this.punit = punit;
	}

	/**
	 * @return the selectedSaleInfo
	 */
	public SaleInfo getSaleInfo() {
		return saleInfo;
	}

	/**
	 * @param selectedSaleInfo the selectedSaleInfo to set
	 */
	public void setSaleInfo(SaleInfo saleInfo) {
		this.saleInfo = saleInfo;
	}

	/**
	 * @return the sale
	 */
	public List<SaleInfo> getSaleInfoList() {
		return sale;
	}

	/**
	 * @param sale the sale to set
	 */
	public void setSaleInfoList(List<SaleInfo> sale) {
		this.sale = sale;
	}

	/**
	 * @return the selectedInventory
	 */
	public ProductInventory getSelectedInventory() {
		return selectedInventory;
	}

	/**
	 * @param selectedInventory the selectedInventory to set
	 */
	public void setSelectedInventory(ProductInventory selectedInventory) {
		this.selectedInventory = selectedInventory;
	}

	/**
	 * @return the productInvs
	 */
	public List<ProductInventory> getProductInvs() {
		return productInvs;
	}

	/**
	 * @param productInvs the productInvs to set
	 */
	public void setProductInvs(List<ProductInventory> productInvs) {
		this.productInvs = productInvs;
	}

	/**
	 * @return the selectedCategory
	 */
	public ProductCategories getSelectedCategory() {
		return selectedCategory;
	}

	/**
	 * @param selectedCategory the selectedCategory to set
	 */
	public void setSelectedCategory(ProductCategories selectedCategory) {
		this.selectedCategory = selectedCategory;
	}

	/**
	 * @return the categories
	 */
	public List<ProductCategories> getCategories() {
		return categories;
	}

	/**
	 * @param categories the categories to set
	 */
	public void setCategories(List<ProductCategories> categories) {
		this.categories = categories;
	}

	/**
	 * @return the selectedcostingInfo
	 */
	public CostingInfo getSelectedcostingInfo() {
		return selectedcostingInfo;
	}

	/**
	 * @param selectedcostingInfo the selectedcostingInfo to set
	 */
	public void setSelectedcostingInfo(CostingInfo selectedcostingInfo) {
		this.selectedcostingInfo = selectedcostingInfo;
	}

	/**
	 * @return the costingInfos
	 */
	public List<CostingInfo> getCostingInfos() {
		return costingInfos;
	}

	/**
	 * @param costingInfos the costingInfos to set
	 */
	public void setCostingInfos(List<CostingInfo> costingInfos) {
		this.costingInfos = costingInfos;
	}
	
	public List<CustomInfo> getCustomFieldList() {
		return customs;
	}

	public void setSelectedCustom(CustomInfo selected) {
		this.custom = selected;
	}

	public CustomInfo getSelectedCustom() {
		return custom;
	}	
	
	public StorageInfo getStorage() {
		return storage;
	}

	public void setStorage(StorageInfo storage) {
		this.storage = storage;
	}
	
	/**
	 * @return the selectedLocation
	 */
	public Inventory getSelectedLocation() {
		return selectedLocation;
	}

	/**
	 * @param selectedLocation the selectedLocation to set
	 */
	public void setSelectedLocation(Inventory selectedLocation) {
		this.selectedLocation = selectedLocation;
	}

	/**
	 * @return the locations
	 */
	public List<Inventory> getLocations() {
		return locations;
	}

	/**
	 * @param locations the locations to set
	 */
	public void setLocations(List<Inventory> locations) {
		this.locations = locations;
	}

	/**
	 * @return the selectedVendor
	 */
	public Vendor getSelectedVendor() {
		return selectedVendor;
	}

	/**
	 * @param selectedVendor the selectedVendor to set
	 */
	public void setSelectedVendor(Vendor selectedVendor) {
		this.selectedVendor = selectedVendor;
	}

	/**
	 * @return the vendors
	 */
	public List<Vendor> getVendors() {
		return vendors;
	}

	/**
	 * @param vendors the vendors to set
	 */
	public void setVendors(List<Vendor> vendors) {
		this.vendors = vendors;
	}
	
	public Vendor getSelectedVendorForTab() {
		return selectedVendorForTab;
	}

	public void setSelectedVendorForTab(Vendor selectedVendorForTab) {
		this.selectedVendorForTab = selectedVendorForTab;
	}

	public List<Vendor> getVendorsForTab() {
		return vendorsForTab;
	}

	public void setVendorsForTab(List<Vendor> vendorsForTab) {
		this.vendorsForTab = vendorsForTab;
	}

	public Vendor getSelectedProductVendor() {
		return selectedProductVendor;
	}

	public void setSelectedProductVendor(Vendor selectedProductVendor) {
		this.selectedProductVendor = selectedProductVendor;
	}

	public List<Vendor> getProductVendors() {
		return productVendors;
	}

	public void setProductVendors(List<Vendor> productVendors) {
		this.productVendors = productVendors;
	}
	
	public List<Inventory> getInventories() {
		return inventories;
	}

	public void setInventories(List<Inventory> inventories) {
		this.inventories = inventories;
	}

	public Inventory getSelectedInvForTab() {
		return selectedInvForTab;
	}

	public void setSelectedInvForTab(Inventory selectedInvForTab) {
		this.selectedInvForTab = selectedInvForTab;
	}

	public List<Inventory> getInvsForTab() {
		return invsForTab;
	}

	public void setInvsForTab(List<Inventory> invsForTab) {
		this.invsForTab = invsForTab;
	}
	
	public String getQuantityOnHand() {
		return quantityOnHand;
	}

	public void setQuantityOnHand(String quantityOnHand) {
		this.quantityOnHand = quantityOnHand;
	}
	
	/**
	 * @return the selectedProductForMaterial
	 */
	public Product getSelectedProductForMaterial() {
		return selectedProductForMaterial;
	}

	/**
	 * @param selectedProductForMaterial the selectedProductForMaterial to set
	 */
	public void setSelectedProductForMaterial(Product selectedProductForMaterial) {
		this.selectedProductForMaterial = selectedProductForMaterial;
	}

	/**
	 * @return the productForMaterial
	 */
	public List<Product> getProductForMaterial() {
		return productForMaterial;
	}

	/**
	 * @param productForMaterial the productForMaterial to set
	 */
	public void setProductForMaterial(List<Product> productForMaterial) {
		this.productForMaterial = productForMaterial;
	}
	
	/**
	 * @return the materials
	 */
	public List<BillMaterial> getMaterials() {
		return materials;
	}

	/**
	 * @param materials the materials to set
	 */
	public void setMaterials(List<BillMaterial> materials) {
		this.materials = materials;
	}

	/**
	 * @return the selectedMaterialForTab
	 */
	public Product getSelectedMaterialForTab() {
		return selectedMaterialForTab;
	}

	/**
	 * @param selectedMaterialForTab the selectedMaterialForTab to set
	 */
	public void setSelectedMaterialForTab(Product selectedMaterialForTab) {
		this.selectedMaterialForTab = selectedMaterialForTab;
	}

	/**
	 * @return the materialForTab
	 */
	public List<BillMaterial> getMaterialForTab() {
		return materialForTab;
	}

	/**
	 * @param materialForTab the materialForTab to set
	 */
	public void setMaterialForTab(List<BillMaterial> materialForTab) {
		this.materialForTab = materialForTab;
	}

	/**
	 * @return the totalCost
	 */
	public int getTotalCost() {
		return totalCost;
	}

	/**
	 * @param totalCost the totalCost to set
	 */
	public void setTotalCost(int totalCost) {
		this.totalCost = totalCost;
	}
	
	/**
	 * @return the selectedMaterialProduct
	 */
	public Product getSelectedMaterialProduct() {
		return selectedMaterialProduct;
	}

	/**
	 * @param selectedMaterialProduct the selectedMaterialProduct to set
	 */
	public void setSelectedMaterialProduct(Product selectedMaterialProduct) {
		this.selectedMaterialProduct = selectedMaterialProduct;
	}

	/**
	 * @return the materialProducts
	 */
	public List<Product> getMaterialProducts() {
		return materialProducts;
	}

	/**
	 * @param materialProducts the materialProducts to set
	 */
	public void setMaterialProducts(List<Product> materialProducts) {
		this.materialProducts = materialProducts;
	}
	
	/**
	 * @return the billMaterial
	 */
	public BillMaterial getBillMaterial() {
		return billMaterial;
	}

	/**
	 * @param billMaterial the billMaterial to set
	 */
	public void setBillMaterial(BillMaterial billMaterial) {
		this.billMaterial = billMaterial;
	}
	
	/**
	 * @return the display
	 */
	public boolean isDisplay() {
		return display;
	}

	/**
	 * @param display the display to set
	 */
	public void setDisplay(boolean display) {
		this.display = display;
	}
	
	/**
	 * @return the media
	 */
	public MediaDTO getMedia() {
		return media;
	}

	/**
	 * @param media the media to set
	 */
	public void setMedia(MediaDTO media) {
		this.media = media;
	}
	
	/**
	 * @return the bufferImg
	 */
	public BufferedImage getBufferImg() {
		return bufferImg;
	}

	/**
	 * @param bufferImg the bufferImg to set
	 */
	public void setBufferImg(BufferedImage bufferImg) {
		this.bufferImg = bufferImg;
	}

	@Init
	public void init(){
		this.getInfomation();
		this.refeshProductGrid();
	}
	
	@NotifyChange({"name","selectedType", "selectedCategory", "description", "selectedcostingInfo"})
	@Command
	public void createProduct(@BindingParam("para") Component tab){
		Tab t = (Tab)tab;
		this.name = "";
		this.type = null;
		this.categories = null;
		this.description = "";
		this.remark = "";
		this.image = "";
		this.sale.clear();
		this.productInvs.clear();
		this.costingInfos = null;
		this.display = false;
		
		t.setSelected(true);
	}
	
	@NotifyChange("products")
	@Command("save")
	public void newProduct(@BindingParam("para") Component tab){
		Product product;
		if(selectedProduct == null){
			product = new Product("7", name, selectedType, description, remark, media, sale, productInvs, selectedCategory, selectedcostingInfo, cost, storageInfoId, selectedLocation, selectedVendor, selectedUnit, selectedSUnit, selectedPUnit, customs);
			productDAO.create(product);
		}else{
			product = new Product(selectedProduct.getId(), name, selectedType, description, remark, media, sale, productInvs, selectedCategory, selectedcostingInfo,cost,storageInfoId,selectedLocation,selectedVendor, selectedUnit, selectedSUnit, selectedPUnit,customs);
			productDAO.update(product);
		}
		
		//save inventories
		saveInventories();		
		
		this.refeshProductGrid();
		Tab t = (Tab)tab;
		t.setSelected(true);
	}
	
	@NotifyChange({"name","selectedType", "selectedCategory", "description", "selectedcostingInfo", "cost", "inventories","quantityOnHand","sale","display","bufferImg"})
	@Command
	public void selectTabInfo(){
		if(selectedProduct == null){
			return;
		}
		
		if(selectedProduct != null){
			this.getAllSaleInfo(selectedProduct.getId());
		}		
		
		updateInv();
		this.getProductInfo();
	}
	
	@NotifyChange({"name","selectedType", "selectedCategory", "description", "selectedcostingInfo", "cost","display","bufferImg"})
	@Command
	public void editProduct(@BindingParam("para") Component tab) {
		Tab t = (Tab)tab;
		if(this.selectedProduct == null){
			Messagebox.show("Please select a product!", "Information", Messagebox.OK, Messagebox.INFORMATION);
			return;
		}
		this.getProductInfo();
		t.setSelected(true);
	}
	
	private void getProductInfo(){
		this.name = this.selectedProduct.getName();
		
		if(this.type!= null && this.selectedProduct.getType() != null)
			for (int i = 0 ; i < this.type.size() ;i++){
				if(this.type.get(i).getName().equals(this.selectedProduct.getType().getName())){
					if(this.type.get(i).getName().equals(Constant.STOCKABLE)){
						this.display = Constant.VISIBLE;
					}else{
						this.display = Constant.INVISIBLE;
					}
					this.selectedType = this.type.get(i);
					break;
				}
			}		
		
		if(this.categories!= null && this.selectedProduct.getCategory() != null)
			for (int i = 0 ; i < this.categories.size() ;i++){
				if(this.categories.get(i).getName().equals(this.selectedProduct.getCategory().getName())){
					this.selectedCategory = this.categories.get(i);
					break;
				}
			}
		
		this.description = this.selectedProduct.getDescription();
		
		if(this.costingInfos!= null && this.selectedProduct.getCostingInfo() != null)
			for (int i = 0 ; i < this.costingInfos.size() ;i++){
				if(this.costingInfos.get(i).getName().equals(this.selectedProduct.getCostingInfo().getName())){
					this.selectedcostingInfo = this.costingInfos.get(i);
					break;
				}
			}
		this.cost = this.selectedProduct.getCost();
		/*
		byte[] data = new MediaDAO().getBinary(Long.parseLong(this.selectedProduct.getId()));
		try {
			AImage newimage = new AImage("abc.gif",data);
			pics.setContent(newimage);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}
	
	public void refeshProductGrid(){
		this.products = this.productDAO.findAll();
		for(Product pros : this.products){
			this.sale = this.saleDAO.findbyProductId(Long.parseLong(pros.getId()));
			if(this.sale.size() != 0){
				pros.setNormalPrice(this.sale.get(0).getSaleValue());
			}
			this.lastVendor = this.vDAO.findLastVendor(Long.parseLong(pros.getId()));
			if(this.lastVendor.size() != 0){
				pros.setLastVendor(this.lastVendor.get(0).getName());
			}
			
			this.storage = new StorageInfoDAO().find(Long.parseLong(pros.getId()));
			if(this.storage != null){
				pros.setStorage(this.storage);
			}else{
				pros.setStorage(new StorageInfo());
			}
		}
	}
	
	public void getInfomation(){
		this.getAllCategory();
		
		this.getAllType();
		
		if(selectedProduct != null){
			this.getAllInventory(selectedProduct.getId());
		}
		
		this.getAllCosting();
		
		this.createCustomField();
		
		this.getAllLocation();
		
		this.getAllVendor();
		
		this.getAllUnit();
		
		this.getAllSUnit();
		
		this.getAllPUnit();
				
	}
	
	private void getAllLocation(){
		InventoryDAO dao = new InventoryDAO();
		locations = dao.findAll();
		selectedLocation = new Inventory("", "", 0);
	}
	
	private void getAllVendor(){
		VendorDAO dao = new VendorDAO();
		vendors = dao.findAll();
		selectedVendor = new Vendor("", "");
	}
	
	private void getAllCategory(){
		ProductCategoriesDAO dao = new ProductCategoriesDAO();
		categories = dao.findAll();
		selectedCategory = new ProductCategories("", "", "");
	}
	
	private void getAllType(){
		TypeDAO dao = new TypeDAO();
		type = dao.findAll();
		selectedType = new Type("", "");
	}

	private void getAllUnit(){
		UnitDAO dao = new UnitDAO();
		unit = dao.findAll();
		selectedUnit = new Unit("", "");
	}
	
	private void getAllSUnit(){
		UnitDAO dao = new UnitDAO();
		sunit = dao.findAll();
		selectedSUnit = new Unit("", "");
	}
	
	private void getAllPUnit(){
		UnitDAO dao = new UnitDAO();
		punit = dao.findAll();
		selectedPUnit = new Unit("", "");
	}	
	
	private void getAllCosting(){
		CostingInfoDAO dao = new CostingInfoDAO();
		costingInfos = dao.findAll();
		selectedcostingInfo = new CostingInfo("", "");
	}
	
	private void getAllSaleInfo(String productId){
		SaleInfoDAO dao = new SaleInfoDAO();
		sale = dao.findbyProductId(Long.parseLong(productId));	
		if(sale == null || sale.size() == 0)
			this.createSaleField();
	}	
	
	private void getAllInventory(String productId){
		ProductInventoryDAO dao = new ProductInventoryDAO();
		productInvs = dao.findAll();
	}
	
	private void createCustomField(){
		// init custom field
		CustomFieldDAO dao = new CustomFieldDAO();
		customs = dao.findAll("Product");
		custom = new CustomInfo();		
	}
	
	private void createSaleField(){
		// init custom field
		this.sale.clear();
		this.sale.add(new SaleInfo("Normal Price", 0));
		this.sale.add(new SaleInfo("Retail Price", 0));
		this.sale.add(new SaleInfo("Wholesale Price", 0));
		this.sale.add(new SaleInfo("","","",0,false));
		this.sale.add(new SaleInfo("","","",0,false));
		this.sale.add(new SaleInfo("","","",0,false));
		this.sale.add(new SaleInfo("","","",0,false));
		this.sale.add(new SaleInfo("","","",0,false));
		this.sale.add(new SaleInfo("","","",0,false));
		this.sale.add(new SaleInfo("","","",0,false));
		this.saleInfo = new SaleInfo();
	}
	
	private void updateProductVendor(String id){
		for(Vendor pro : productVendors){
			if(pro.getId().equals(id)){
				pro.copyValue(selectedVendorForTab);
				break;
			}
		}
		if(!productVendors.get(productVendors.size() - 1).getId().equals(""))
			productVendors.add(new Vendor("", ""));
	}
	
	
	private void updateVendor(){
		VendorDAO dao = new VendorDAO();
		vendorsForTab = dao.findAll();
		//selectedVendorForTab = vendorsForTab.get(0);
					
		productVendors = dao.findByProductID(Long.parseLong(selectedProduct.getId()));
		productVendors.add(new Vendor("", ""));			
	}
	
	private void updateInvProduct(String id){
		for(Inventory pro : inventories){
			if(pro.getId().equals(id)){
				pro.copyValue(selectedInvForTab);
				break;
			}
		}
		if(!inventories.get(inventories.size() - 1).getId().equals(""))
			inventories.add(new Inventory());
	}
	
	
	private void updateInv(){		
		InventoryDAO dao = new InventoryDAO();
		invsForTab = dao.findAll();
		//selectedVendorForTab = vendorsForTab.get(0);
		
		if(selectedProduct!= null){
			inventories = dao.findByProductID(Long.parseLong(selectedProduct.getId()));					
		}else{
			inventories = new ArrayList<Inventory>();
		}
		
		sumProductQuantity();
		
		inventories.add(new Inventory());
		
		
	}
	
	private void sumProductQuantity(){
		quantityOnHand = "Quatity on hand : "; 
		int sum = 0;
		for(Inventory inv : inventories){
			sum += inv.getQuantity();
		}			
		quantityOnHand += sum + " ea";
	}
	
	@NotifyChange("products")
	@Command
	public void deleteProduct() {	
		if(this.selectedProduct == null){ 
			Messagebox.show("Please choice a product!", "Information", Messagebox.OK, Messagebox.INFORMATION);
			return;		
		}		
		//Messagebox.show("Are you sure to delete?", "Confirm Dialog", Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION, this); 
		
		this.productDAO.delete(this.selectedProduct);	
    	this.refeshProductGrid();  
	}
	
	@NotifyChange({ "storage", "remark", "selectedLocation", "selectedVendor","selectedUnit","selectedSUnit","selectedPUnit","materialProducts","products","totalCost"})
	@Command
	public void selectTabExtra(@BindingParam("para") Component tab) {
		Tab t = (Tab)tab;
		if(this.selectedProduct == null){
			Messagebox.show("Please choice a product!", "Information", Messagebox.OK, Messagebox.INFORMATION);
			return;
		}
		this.getMaterialsProducts();
		this.getProductExtra();
		t.setSelected(true);
	}
	
	private void getProductExtra(){
		this.remark = this.selectedProduct.getRemark();
		if(Long.parseLong(this.selectedProduct.getStorageInfoId()) != 0 ){
			this.storage = new StorageInfoDAO().find(Long.parseLong(this.selectedProduct.getStorageInfoId()));
		}
		if(this.locations!= null && this.selectedProduct.getLocation() != null)
			for (int i = 0 ; i < this.locations.size() ;i++){
				if(this.locations.get(i).getName().equals(this.selectedProduct.getLocation().getName())){
					this.selectedLocation = this.locations.get(i);
					break;
				}
			}

		if(this.vendors!= null && this.selectedProduct.getVendor() != null)
			for (int i = 0 ; i < this.vendors.size() ;i++){
				if(this.vendors.get(i).getName().equals(this.selectedProduct.getLastVendor())){
					this.selectedVendor = this.vendors.get(i);
					break;
				}
			}
		
		if(this.unit!= null && this.selectedProduct.getStandardUoM() != null)
			for (int i = 0 ; i < this.unit.size() ;i++){
				if(this.unit.get(i).getName().equals(this.selectedProduct.getStandardUoM().getName())){
					this.selectedUnit = this.unit.get(i);
					break;
				}
			}
		
		if(this.sunit!= null && this.selectedProduct.getSaleUoM() != null)
			for (int i = 0 ; i < this.sunit.size() ;i++){
				if(this.sunit.get(i).getName().equals(this.selectedProduct.getSaleUoM().getName())){
					this.selectedSUnit = this.sunit.get(i);
					break;
				}
			}
		
		if(this.punit!= null && this.selectedProduct.getPurchaseUoM() != null)
			for (int i = 0 ; i < this.punit.size() ;i++){
				if(this.punit.get(i).getName().equals(this.selectedProduct.getPurchaseUoM().getName())){
					this.selectedPUnit = this.punit.get(i);
					break;
				}
			}
	}
	
	@NotifyChange("products")
	@Command("saveExtra")
	public void updateExtraProduct(@BindingParam("para") Component tab) {	
		Product product;
		product = new Product(this.selectedProduct.getId(), this.remark, this.storage, this.selectedLocation, this.selectedVendor, this.selectedUnit, this.selectedSUnit, this.selectedPUnit);
		this.productDAO.updateExtra(product);
		this.saveMaterials();
		this.refeshProductGrid();
		Tab t = (Tab)tab;
		t.setSelected(true);
	}	
	
	@NotifyChange("customs")
	@Command
	public void updateCustomField(@BindingParam("dlg") Window win) {		
		win.onClose();
	}	
	
	@NotifyChange("productVendors")
	@Command
	public void addToProduct() {	
		VendorProductDAO dao = new VendorProductDAO();
		for(Vendor pro : productVendors){
			if(!pro.getId().equals("")){
				if(dao.findProductsByVendorId(Long.parseLong(pro.getId())).size() != 0){
					if(pro.isDeleted()){
						dao.delete(new VendorProduct("", pro.getId(), selectedProduct.getId()));
					}
				}else{
					dao.create(new VendorProduct("", pro.getId(), selectedProduct.getId()));
				}	
			}
		}
		
		VendorDAO venDao = new VendorDAO();							
		productVendors = venDao.findByProductID(Long.parseLong(selectedProduct.getId()));
		productVendors.add(new Vendor("", ""));

	}	
	
	@NotifyChange("productVendors")
	@Command
	public void addVendorToProduct(@BindingParam("para") Component comp, @BindingParam("vendorId")String vendorId) {
		// manipulate data		
		Component parent = comp.getParent();
		parent = parent.getParent();
		parent = parent.getParent();
		Bandbox box = (Bandbox)parent;
		updateProductVendor(vendorId);
		box.close();		 	
	}
	
	@NotifyChange("productVendors")
	@Command
	public void addProductToInv(@BindingParam("para") Component comp, @BindingParam("invId")String invId) {
		// manipulate data		
		Component parent = comp.getParent();
		parent = parent.getParent();
		parent = parent.getParent();
		Bandbox box = (Bandbox)parent;
		updateInvProduct(invId);
		box.close();		 	
	}
	
	@NotifyChange("sale")
	@Command
	public void updatePriceList(@BindingParam("dlg") Window win) {
		// manipulate data		
		win.onClose();		 	
	}	
	
	@NotifyChange({"productVendors" , "vendorsForTab"})
	@Command
	public void vendorProductTabSelect() {
		updateVendor();
	}

	private void saveInventories(){
		ProductInventoryDAO dao = new ProductInventoryDAO();
		for(Inventory inv : inventories){
			if(!inv.getId().equals("")){
				if(dao.findByInvID(Long.parseLong(inv.getId())).size() != 0){
					if(inv.isDeleted()){
						dao.delete(new ProductInventory("", selectedProduct.getId(),inv.getId(),1,""));
					}else{
						dao.update(new ProductInventory("", selectedProduct.getId(),inv.getId(),inv.getQuantity(),""));						
					}
				}else{
					dao.create(new ProductInventory("", selectedProduct.getId(),inv.getId(),inv.getQuantity(),""));
				}	
			}
		}
	}
	
	private void saveSaleInfo(){
		SaleInfoDAO dao = new SaleInfoDAO();
		for(SaleInfo saleInfo: sale){
			
			if(saleInfo.getProductId() == null || saleInfo.getProductId().equals(""))
				saleInfo.setProductId(selectedProduct.getId());
			
			if(saleInfo.getId() == null || saleInfo.getId().equals("")){				
				dao.create(saleInfo);
			}else{
				dao.update(saleInfo);
			}
		}
	}	
	
	@NotifyChange("products")
	@Command
	public void addProductToMaterial(@BindingParam("para") Component comp, @BindingParam("pId")String pId) {
		// manipulate data		
		Component parent = comp.getParent();
		parent = parent.getParent();
		parent = parent.getParent();
		Bandbox box = (Bandbox)parent;
		updateBillProduct(pId);
		box.close();		 	
	}
	
	private void updateBillProduct(String id){
		for(Product product : this.materialProducts){
			if(product.getId().equals(id)){
				product.copyMaterialValue(this.selectedMaterialForTab);
				break;
			}
		}
		if(!materialProducts.get(materialProducts.size() - 1).getId().equals(""))
			materialProducts.add(new Product("","","","",""));
	}
	
	private void getMaterialsProducts(){
		int total = 0;
		this.products = productDAO.findAll();
		
		for(Product pros : this.products){
			this.sale = this.saleDAO.findbyProductId(Long.parseLong(pros.getId()));
			if(this.sale.size() != 0){
				pros.setNormalPrice(this.sale.get(0).getSaleValue());
			}	
		}
		BillMaterialDAO dao = new BillMaterialDAO();
		this.materialProducts = this.productDAO.findByMaterialProductID(Long.parseLong(this.selectedProduct.getId()));
		for(Product product : this.materialProducts){
			this.materials = dao.findMaterial(Long.parseLong(this.selectedProduct.getId()),Long.parseLong(product.getId()));
			product.setQuantity(this.materials.get(0).getNumber());
			total += Long.parseLong(product.getCost());			
		}
		this.materialProducts.add(new Product("", "", "", "", ""));
		this.totalCost = total;
	}
	
	private void saveMaterials(){
		BillMaterialDAO dao = new BillMaterialDAO();
		for(Product product : this.materialProducts){
			if(!product.getId().equals("")){
				if(dao.findMaterial(Long.parseLong(this.selectedProduct.getId()), Long.parseLong(product.getId())).size() != 0){
					billMaterial.setProductId(this.selectedProduct.getId());
					billMaterial.setMaterialId(product.getId());
					billMaterial.setNumber(product.getQuantity());
					dao.update(billMaterial);					
				}else{
					billMaterial.setProductId(this.selectedProduct.getId());
					billMaterial.setMaterialId(product.getId());
					billMaterial.setNumber(product.getQuantity());
					dao.create(billMaterial);
				}	
			}
		}
	}
	
	public void uploadImage(Media media, String id) throws InterruptedException {
        //If user selects a real file...
        if (media != null) {
            BufferedWriter writer = null;
            File file = null;
            try {
                //Read the file data from media to a tmp file...
                file = File.createTempFile("temporal_", ".borrame");
                if (media.isBinary()) {
                    Files.copy(file, media.getStreamData());
                } else {
                    writer = new BufferedWriter(new FileWriter(file));
                    Files.copy(writer, media.getReaderData());
                }

                //make sure we could read file content correctly... 
                int tamanio = (int)file.length();
                if (tamanio <=0){
                    if(file.exists()){
                        file.delete();
                    }
                    if (writer != null){
                        writer.close();
                    }
                    throw new IOException("Imposible to load file[" + media.getName() + "], ["+tamanio+"] bytes read. ");
                }

                String type = media.getContentType();
                String name = media.getName();
                byte[] byteImage = media.getByteData();
                MediaDAO mDao = new MediaDAO();     
                MediaDTO mdto = new MediaDTO();
                mdto.setProductId(id);
                mdto.setName(name);
                mdto.setMimeType(type);
                mdto.setObject(byteImage);
                mDao.create(mdto);
                				
                //lets clean the tmp file
                boolean borrado = file.delete();
                //and tell the user we aleady saved the file
            } catch (IOException e) {
                file.delete();
            } catch (Exception e) {
                file.delete();                
            } finally {
                try {
                    if(file.exists()){
                        file.delete();
                    }
                    if (writer != null){
                        writer.close();
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
	
	public void displayImage(){
		
	}
}